package pl.edu.pw.ee.buildcity.notifiers;

import com.sun.syndication.feed.synd.*;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.SyndFeedOutput;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.tools.generic.DateTool;
import org.apache.velocity.tools.generic.ListTool;
import org.springframework.ui.velocity.VelocityEngineUtils;
import pl.edu.pw.ee.buildcity.entities.BuildActivity;
import pl.edu.pw.ee.buildcity.services.BuildActivityService;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Mateusz
 * @since 2010-03-14
 */
public class RSSFeedPublisher {

	private static final int NUMBER_OF_ACTIVITIES_TO_FETCH = 20;
	private static final String FEED_TYPE = "rss_2.0";
	private static final String SUBJECT_TEMPLATE = "build-notification-rss-subject-template.vm";
	private static final String BODY_TEMPLATE = "build-notification-rss-body-template.vm";

	@Resource(name = "buildActivityService")
	private BuildActivityService buildActivityService;

	@Resource(name = "velocityEngine")
	protected VelocityEngine velocityEngine;

	public String publish(String buildDefinitionName) throws FeedException {

		List<BuildActivity> buildActivities = buildActivityService.getLatestBuildActivities(buildDefinitionName, NUMBER_OF_ACTIVITIES_TO_FETCH);
		List<SyndEntry> entries = createEntriesWithLatestBuildActivities(buildActivities);

		SyndFeed syndFeed = createFeed();
		syndFeed.setEntries(entries);

		SyndFeedOutput output = new SyndFeedOutput();
		return output.outputString(syndFeed);
	}

	private SyndFeed createFeed() throws FeedException {
		SyndFeed feed = new SyndFeedImpl();
		feed.setFeedType(FEED_TYPE);
		feed.setLink("http://buildcity"); //Exception if no link is specified :(
		feed.setTitle("BuildCity Feed");
		feed.setDescription("This feed is syndicating news about latest build activities");

		return feed;
	}

	private List<SyndEntry> createEntriesWithLatestBuildActivities(List<BuildActivity> buildActivities) {
		List<SyndEntry> entries = new ArrayList<SyndEntry>();

		for (BuildActivity ba : buildActivities) {
			SyndEntry entry = createEntry(ba);
			entries.add(entry);
		}
		return entries;
	}

	private SyndEntry createEntry(BuildActivity ba) {
		SyndEntry entry = new SyndEntryImpl();

		Map<String, Object> model = createModel(ba);
		entry.setTitle(fillTemplate(SUBJECT_TEMPLATE, model));

		//TODO Link to build activity logs...
		//entry.setLink("http://wiki.java.net/bin/view/Javawsxml/Rome01");

		SyndContent description = new SyndContentImpl();
		description.setType("text/html");
		description.setValue(fillTemplate(BODY_TEMPLATE, model));
		entry.setDescription(description);
		return entry;
	}

	private Map<String, Object> createModel(BuildActivity buildActivity) {
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("formatter", new DateTool()); //to format dates in template...
		model.put("listTool", new ListTool()); //to check if commits list is empty...
		model.put("buildActivity", buildActivity);
		return model;
	}

	private String fillTemplate(String templateFileName, Map<String, Object> model) {
		String mergedTemplate = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, templateFileName, model);
		return mergedTemplate;
	}
}
